/**
* PlaylistPlayer
* @author maze | guavestudios.com
* @version 0.1 alpha
*/

package ch.sfug.player {
	import ch.sfug.events.PlayerEvent;
	import ch.sfug.events.PlaylistEvent;
	import ch.sfug.events.TimeProgressEvent;
	import ch.sfug.net.loader.AbstractLoader;
	import ch.sfug.player.AbstractPlayer;
	import ch.sfug.player.IExternalPlayer;
	import flash.events.EventDispatcher;
	import flash.events.ProgressEvent;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;

	//{ EVENT DEFINITION
	/**
	* PlaylistEvent.NEXT dispatched next item played
	*/
	[Event(name = "PlaylistEvent.NEXT", type = "ch.sfug.events.PlaylistEvent")]
	/**
	* PlaylistEvent.PREV dispatched previous item played
	*/
	[Event(name = "PlaylistEvent.PREV", type = "ch.sfug.events.PlaylistEvent")]
	/**
	* PlaylistEvent.ENDLIST dispatched when the last element in is was played
	*/
	[Event(name="PlaylistEvent.ENDLIST",type="ch.sfug.events.PlaylistEvent")]
	//}
	
	/**
	 * !!NOTE: ALPHA! Player is working, but not finished, maybe the api change.
	 * 
	 * a player which can play playlists
	 * The player needs to implement IExternalPlayer
	 * 
	 * @example <listening version="3">
	 * var p:PlaylistPlayer=new PlaylistPlayer(new Mp3Player());
	 * p.setPlaylist([new UrlRequest("test.mp3")]);
	 * p.next();
	 * 
	 * </listening>
	 * 
	 * @todo think about the extend, maybe alter to combound as external player controller, bound with events
	 */
	public class PlaylistPlayer extends AbstractPlayer implements ISoundProvider,IExternalPlayer {
		
		//{ STATIC
		
		//}
		
		//{ MEMBERS
		private var player:AbstractPlayer; //hosted player
		
		private var playlist:Array; //<UrlRequest>
		private var playlistPos:int=-1; //playlist position
		
		
		//}
		
		//{ GETTER-SETTER
		/**
		 * @inheritDoc
		 */
		public function get loader():AbstractLoader
		{
			return IExternalPlayer(player).loader;
		}
		//}
		
		
		
		//{ INIT
		/**
		 * 
		 * @param	p	The player to be controlled
		 */
		public function PlaylistPlayer(p:AbstractPlayer) {
			
			setPlayer(p);
			
			init();
		}
		private function init():void {
			playlistPos = 0;
		}
		//}
		
		//{ PUBLIC METHODS
		/**
		 * Sets the player to be controlled
		 * @param	p	player
		 */
		public function setPlayer(p:AbstractPlayer):void
		{
			if (player)
			{
				player.removeEventListener(PlayerEvent.END, player_endstate);
			}
			if (p is IExternalPlayer)
			{
				player = p;
				
				player.addEventListener(PlayerEvent.END, player_endstate);
			}
			else
			{
				throw new Error("Only IExternalPlayer devices supported");
			}
		}
		/**
		 * Sets the playlist 
		 * @param	p	Array<UrlRequest>
		 */
		public function setPlaylist(p:Array):void
		{
			playlistPos = -1;
			playlist = p;
		}
		/**
		 * Proceed to next track
		 */
		public function next():void
		{
			if (playlistPos+1 < playlist.length)
			{
				stop();
				
				playlistPos++;
				internalLoad(playlist[playlistPos]);
				
				dispatchEvent(new PlaylistEvent(PlaylistEvent.NEXT,playlist,playlistPos));
				
				play();
			}
		}
		/**
		 * Play previous track
		 */
		public function previous():void
		{
			if (playlistPos - 1 >= 0)
			{
				stop();
				
				playlistPos--;
				internalLoad(playlist[playlistPos]);
				
				dispatchEvent(new PlaylistEvent(PlaylistEvent.NEXT, playlist, playlistPos));
				
				play();
			}
		}
		/**
		 * Goto and play track on playlist position
		 * @param	n	playlistposition
		 */
		public function goto(n:int):void
		{
			if (n > 0 && n < playlist.length)
			{
				stop();
				
				playlistPos=n;
				internalLoad(playlist[playlistPos]);
				
				play();
			}
		}
		//}
		
		//{ OVERRIDEN METHODS
		/**
		 * @inheritDoc
		 */
		public override function get duration():Number {
			return  player.duration;
		}
		/**
		 * @inheritDoc
		 */
		public override function get time():Number {
			return player.time;
		}
		/**
		 * @inheritDoc
		*/
		internal override function loadPlayer():void {
			player.play();
		}
		
		/**
		 * @inheritDoc
		 */
		override internal function stopPlayer():void {
			player.stop();
		}
		/**
		 * @inheritDoc
		 */
		override internal function pausePlayer():void {
			if (!player.isPaused()) player.pause();
		}
		/**
		 * @inheritDoc
		 */
		override internal function seekPlayerTo( time:Number ):void {
			player.seek(time);
		}
		
		/**
		 * @inheritDoc
		 */
		override internal function resumePlayer(  ):void {
			if (player.isPaused()) player.pause();
		}
		
		/**
		 * @inheritDoc
		 */
		override internal function restartPlayer(  ):void {
		}
		
		/**
		 * @inheritDoc
		 */
		override internal function seekFromEndTo( time:Number ):void {
			//player.seek( time );
		}
		public function get soundTransform():SoundTransform
		{
			if (player is ISoundProvider)
				return ISoundProvider(player).soundTransform;
			return null;
		}
		public function set soundTransform(t:SoundTransform):void
		{
			if (player is ISoundProvider)
				ISoundProvider(player).soundTransform = t;
		}
		//}
		
		//{ PRIVATE METHODS
		private function internalLoad(url:URLRequest):void
		{
			IExternalPlayer(player).loader.load(url);
		}
		//}
		
		//{ EVENT HANDLING
		private function player_endstate(e:PlayerEvent):void
		{
			if (isPlaying()) 
			{
				if (playlistPos +1 < playlist.length)
					next();
				else
				{
					setEndState();
					dispatchEvent(new PlaylistEvent(PlaylistEvent.ENDLIST, playlist, playlistPos));
				}
			}
			
		}
		private function player_progress(e:ProgressEvent):void
		{
			dispatchEvent(e);
		}
		//}
		
	}
	
}
